--Universidade Federal de Campina Grande
--Centro de Enegenharia Elétrica e Informática
--Unidade Acadêmica de Sistemas e Computação
--Disciplina: Paradigmas de Linguagens de Programação
--Professor: Franklin Ramalho
--Equipe: Arthur Ribeiro
--        Felipe Vieira
--        Jeysibel Dantas
--        Paulo Victor
--Euphoric Checkers
--Arquivo: game.ex
--Descrição: Esta Unidade de compilação compreende os atributos e 
--           funções da Entidade Game

include board.ex
include get.e
include utils.ex
include moves.ex
include takes.ex
include textUI.ex
include chooser.ex
--include win32lib.ew


--Game Status
global atom gameRunning
atom whiteLose
atom blackLose

--Game Components
global sequence board

--Game data
global constant EMPTY = 0
global constant WHITE = 1
global constant BLACK = 2
global constant WHITE_KING = 3
global constant BLACK_KING = 4
global atom tieCount = 0



--Initializes the game State and then startup the game
export procedure startGame ()
  initializeGameState()
  while gameRunning and (not blackLose) and (not whiteLose) do   
    whitePlay()     
    blackPlay()   
  end while
end procedure

--Check if the white player Win the match
export function isWhiteWinner()
  for i=1 to length(board) do
    for j=1 to length(board[i]) do
        if board[i][j]=2 or board[i][j]=4 then
            return FALSE
        end if
    end for
end for

blackLose = TRUE

return TRUE
end function 

export function isTie()
    return tieCount>=20
end function

--Check if the black player Win the match
export function isBlackWinner()
  for i=1 to length(board) do
    for j=1 to length(board[i]) do
        if board[i][j]=1 or board[i][j]=3 then
            return FALSE
        end if
    end for
end for

whiteLose = TRUE

return TRUE
end function

--Initialize variables to a default state
procedure initializeGameState()
        gameRunning = TRUE
        whiteLose = FALSE
        blackLose = FALSE
        board =initializeBoard()
--board = {
--   {0,0,3,0,0,0,0,0},
--   {0,0,0,0,0,0,0,0},
--   {0,0,0,0,2,0,0,0},
--   {0,0,0,0,0,0,0,0},
--   {0,0,0,0,0,0,0,0},
--   {0,0,0,0,0,0,0,0},
--     {0,0,0,0,0,0,0,0},
--   {0,0,0,0,0,0,0,0}
--}

end procedure


function acquireValidCellsLocation(atom player)
    
    object lineStart
    object columnStart
    object lineStop
    object columnStop
    atom lineStartChoice
    atom columnStartChoice
    atom lineStopChoice
    atom columnStopChoice
    atom startCellExists = FALSE
    atom startPieceExists = FALSE
    atom stopCellExists = FALSE
    atom stopCellEmpty = FALSE
    atom validMove = TRUE

    puts(1,"\nDigite a linha da peca que voce deseja mexer: ")  
    lineStart = value(gets(0))  
    puts(1,"\nDigite a coluna da peca que voce deseja mexer: ")  
    columnStart = value(gets(0)) 
    puts(1,"\nDigite a linha de destino da peca que voce deseja mexer: ")  
    lineStop = value(gets(0))  
    puts(1,"\nDigite a coluna de destino da peca que voce deseja mexer: ")  
    columnStop = value(gets(0)) 
    --Acquirying Values
    lineStartChoice = lineStart[2]
    columnStartChoice = columnStart[2] 
    lineStopChoice = lineStop[2]
    columnStopChoice = columnStop[2]  
    
    --puts(1,"Entradas do usuário: \n")
    --?lineStartChoice
    --?columnStartChoice
    --?lineStopChoice
    --?columnStopChoice
    
        -- Invalid inputs
    if not (isBetween(lineStartChoice, {1,8}) and isBetween(columnStartChoice,{1,8}) and isBetween(lineStopChoice, {1,8}) and isBetween(columnStopChoice, {1,8})) then
        return acquireValidCellsLocation(player)
    end if
    
    startCellExists =  isValidPosition(lineStartChoice, columnStartChoice) 
    stopCellExists = isValidPosition(lineStopChoice, columnStopChoice)
    if(equal(player, WHITE)) then
        startPieceExists =  verifyWhitePieceExistence(lineStartChoice, columnStartChoice)
        stopCellEmpty = not verifyPieceExistence(lineStopChoice, columnStopChoice)
        --validMove = isWhiteValidMove(lineStartChoice,columnStartChoice,lineStopChoice,columnStopChoice)
    end if
        
    if(equal(player,BLACK)) then 
        startPieceExists = verifyBlackPieceExistence(lineStartChoice, columnStartChoice)
        stopCellEmpty = not verifyPieceExistence(lineStopChoice, columnStopChoice)
        --validMove = isBlackValidMove(lineStartChoice,columnStartChoice,lineStopChoice,columnStopChoice)
    end if
    
    if (equal(board[lineStartChoice][columnStartChoice],WHITE_KING)) then       
        startPieceExists =  verifyWhitePieceExistence(lineStartChoice, columnStartChoice)
        stopCellEmpty = not verifyPieceExistence(lineStopChoice, columnStopChoice)
        
        validMove = isValidKingMove(WHITE,{lineStartChoice,columnStartChoice,lineStopChoice,columnStopChoice})
    
        
        --printf(1,"VALID MOVE EEEEEEEEEEH %d",{validMove})
    end if
    
    if (equal(board[lineStartChoice][columnStartChoice],BLACK_KING)) then       
        startPieceExists =  verifyBlackPieceExistence(lineStartChoice, columnStartChoice)
        stopCellEmpty = not verifyPieceExistence(lineStopChoice, columnStopChoice)
        validMove = isValidKingMove(BLACK,{lineStartChoice,columnStartChoice,lineStopChoice,columnStopChoice})
    end if
    

    --?startCellExists
    --?stopCellExists
    --?startPieceExists
    --?stopCellEmpty
    --?validMove
    
    if board[lineStartChoice][columnStartChoice]=3 or board[lineStartChoice][columnStartChoice]=4 then
        if startCellExists and stopCellExists and startPieceExists and validMove then
            return {lineStartChoice,columnStartChoice,lineStopChoice,columnStopChoice}
        end if
    end if
    
    if startCellExists and stopCellExists and startPieceExists and stopCellEmpty and validMove then
        return {lineStartChoice,columnStartChoice,lineStopChoice,columnStopChoice}
    else 
        
        puts(1,"\n==================================================\n")
        puts(1,"         Dados Invalidos, tente novamente           \n")
        puts(1,"==================================================\n")
        return acquireValidCellsLocation(player)
    end if
end function


function isKingOperation(sequence operChoosen)
atom startLine = operChoosen[1]
atom stopLine = operChoosen[2]

if equal(board[startLine][stopLine],WHITE_KING) or equal(board[startLine][stopLine],BLACK_KING) then
  return TRUE
end if
return FALSE

end function


function isWhiteKingOperation(sequence operChoosen)
atom startLine = operChoosen[1]
atom stopLine = operChoosen[2]

if equal(board[startLine][stopLine],WHITE_KING) then
  return TRUE
end if
return FALSE

end function

function isBlackKingOperation(sequence operChoosen)
atom startLine = operChoosen[1]
atom stopLine = operChoosen[2]

if equal(board[startLine][stopLine],BLACK_KING) then
  return TRUE
end if
return FALSE

end function




--  
procedure whitePlay()   
    drawBoard(board)
    puts(1,"\n\nBRANCAS JOGAM\n\n") 
    sequence requiredTakes = {}
    sequence operChoosen = {}
    sequence possibleMoves = {}
    atom takeRequired = FALSE
    sequence possibleTakes = {} 
    atom performed = TRUE
    possibleTakes = verifyWhitePossibleTakes()
    possibleMoves = verifyPossibleMoves(board,WHITE)
    --user input
    operChoosen = acquireValidCellsLocation(WHITE)
    
    atom kingOperation = isKingOperation(operChoosen)

  
  if(kingOperation) then 




--------------------------
-- Teu Código Aqui
--------------------------
        if isBlackKingOperation(operChoosen) then
                if isValidKingMove(BLACK_KING,operChoosen) then 
                   --- perform ---- 
                    performKingMove(BLACK_KING,operChoosen)
                    isBlackWinner()
                if theresOnlyKings() then tieCount+=1 end if
                end if
        
        elsif isWhiteKingOperation(operChoosen) then             
                if isValidKingMove(WHITE_KING,operChoosen) then 
                  --- perform ----
        
                    performKingMove(WHITE_KING,operChoosen)
                    isWhiteWinner()
                if theresOnlyKings() then tieCount+=1 end if
                end if
        end if 

    else

        if length(possibleTakes)>0 then         
            --puts(1,"entrei no if takes")
            for i=1 to length(possibleTakes) do      
                atom canTake = verifyIfCanTakeEnemy(operChoosen[1],operChoosen[2],operChoosen[3],operChoosen[4],possibleTakes[i])
                --?canTake
                if equal(canTake,TRUE) then
                  performTakes(possibleTakes[i])                  
                  verifyAndCreateKings()
                  puts(1,"foi")
                  isWhiteWinner()                    
                end if
            end for
            --compare to infer if the user have choose the better take
            while not performed do
                puts(1,"\n\n========================================================================================\n")
                puts(1,"Existe uma Comida Obrigatoria diferente da solicitada no tabuleiro, tente novamente:    \n")
                puts(1,"========================================================================================\n\n")
                --choose an another place to play
                whitePlay()
            end while
        end if 
        if length(possibleMoves)>0 and (length(possibleTakes)<1) then
            --puts(1,"entrei no if moves\n")
            atom canMove = isWhiteValidMove(operChoosen[1],operChoosen[2],operChoosen[3],operChoosen[4])
            --?canMove
            if canMove then                     
                performMove(WHITE,operChoosen)
                verifyAndCreateKings()
                isWhiteWinner() 
                        
            else                
                puts(1,"\n\n========================================================================================\n")
                puts(1,"Movimento Invalido, tente novamente:    \n")
                puts(1,"========================================================================================\n\n")
                whitePlay()
            end if
        end if
    end if

  
end procedure

procedure blackPlay()   
drawBoard(board)

    puts(1,"\n\nPRETAS JOGAM\n\n")
    puts(1,"\n\n===========================================================================")
    puts(1,"             Aguarde enquanto o Computador executa sua jogada...           ")
    puts(1,"\n===========================================================================")
     sequence requiredTakes = {}
    sequence operChoosen = {}
    sequence possibleMoves = {}
    atom takeRequired = FALSE
    sequence possibleTakes = {} 
    possibleTakes = verifyBlackPossibleTakes()
    possibleMoves = verifyPossibleMoves(board,BLACK)
    if length(possibleTakes)>0 then
        atom canTake = FALSE
              performTakes(possibleTakes[1])
              verifyAndCreateKings()
              isBlackWinner()                    
    end if 
    
    if length(possibleMoves)>0 and (length(possibleTakes)<1) then
        operChoosen = chooseBetterMove(board,BLACK, possibleMoves)
        atom canMove = isBlackValidMove(operChoosen[1],operChoosen[2],operChoosen[3],operChoosen[4])
        if canMove then
             performMove(BLACK,operChoosen)
             verifyAndCreateKings()
             isBlackWinner()
            if theresOnlyKings() then tieCount+=1
            end if
        else
            puts(1,"\n\n========================================================================================\n")
            puts(1,"Alguma coisa Errada: Black Play   \n")
            puts(1,"========================================================================================\n\n")
            blackPlay()
        end if
    end if

    
end procedure
